package com.seesmic.methodgroups
{
	import com.seesmic.SeesmicService;
	import com.seesmic.ServiceBase;
	import com.seesmic.events.SeesmicResultEvent;
	
	import flash.events.NetStatusEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.TimerEvent;
	import flash.media.Camera;
	import flash.media.Microphone;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.utils.Timer;

	public class Recording extends MethodGroup
	{
	 
		protected var _nc:NetConnection;
		private var _ns:NetStream ;
		private var _camera:Camera
		private var _microphone:Microphone
		
		public function Recording(service:ServiceBase)
		{
			//TODO: implement function
			super(service);
		}
		
		public function get seesmicService():SeesmicService
		{
			return this.service as SeesmicService
		}
		
		/**
		 * Set Camera
		 * */
		public function setCamera(camera:Camera):void
		{
			this._camera = camera	
		}
		
		/**
		 * Set Microphone
		 * */
		public function setMicrophone(mic:Microphone):void
		{
			this._microphone = mic
		}
		
		/**
		 * beginRecord with token
		 * */
		 private var   recordingToken:String
		 public function get currentToken():String
		 {
		 	return this.recordingToken
		 }
		public function beginRecord(recordingToken:String):void
		{
			this.recordingToken = recordingToken;
			
			// Create a NetConnection object
 			_nc  = new NetConnection();

			// Add handlers for connection events
			_nc.addEventListener(NetStatusEvent.NET_STATUS, statusHandler);
			_nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, netSecurityError);

			_nc.client = this;

			// Set the encoding to AMF0
			_nc.objectEncoding = flash.net.ObjectEncoding.AMF0;

			// Connect to rmtp server
			
			if(seesmicService.session_id != null)
			{
				_nc.connect
				(
					SeesmicService.RECORDING_END_POINT,
					recordingToken, 
					seesmicService.session_id, 
					seesmicService.username
				);
			}
			else
			{
				_nc.connect
				(
					SeesmicService.RECORDING_END_POINT,
					recordingToken
					 
				);
			}
		}
		
		// NetConnection status handler
		protected function statusHandler(e:NetStatusEvent):void
		{

		    if (e.info.code == "NetConnection.Connect.Success"){

      			  initStream();

  		  } 
  		  else {
        		trace( "Connection error:" + e.info.code );			
   			 }

		}
		
		protected function netSecurityError(e:SecurityErrorEvent):void
		{
			
		}
		
		
		// Init stream after connection is ready
		
		private var  recordingClient:Object = new Object()
		private function initStream():void
		{

    		// Create the NetStream
    		_ns = new NetStream(_nc);

   			 // Add handlers for stream events
 			_ns.client = this
 	 		this.streamMaxDurationReached = streamMaxDurationReachedHandler
    		_ns.addEventListener(NetStatusEvent.NET_STATUS, streamStatusHandler);
  
   
    		// Attach the camera and mic to the NetStream
    		_ns.attachCamera(_camera);
    		_ns.attachAudio(_microphone);
    		
    		// Disable your recording button  
    		startRecording()

		}
		
		// Start recording
		private var timer:Timer
		protected function startRecording():void
		{
	

    		_ns.publish(recordingToken, "record");

   			 _nc.call("FCPublish",null, recordingToken);

   			
   			//Dispatch event
   			service.dispatchEvent(new SeesmicResultEvent(SeesmicResultEvent.RECORDING_START_RECORD))
   			startTimer()
   			

		}
		
		
		private function startTimer():void
		{
			if(timer == null)
			{
				timer = new Timer(1000,0)
				timer.addEventListener(TimerEvent.TIMER, onTimer)
			}
			timer.reset()
			timer.start()
		}
		protected function onTimer(e:TimerEvent):void
		{
			service.dispatchEvent(new SeesmicResultEvent(SeesmicResultEvent.RECORDING_TIMER, timer.currentCount))
			if(timer.currentCount >= minimumtime)
			{
				service.dispatchEvent(new SeesmicResultEvent(SeesmicResultEvent.RECORDING_MINIMUM_TIME))
			}
		}

		private var minimumtime:Number = 5
		public function endRecord():void
		{
			if(timer.currentCount >= minimumtime)
			stopRecording()
		}
		// Stop recording
		protected function stopRecording():void
		{
	
			if(timer != null)
			{	
				timer.stop()
			} 
  			  // Detach camera
  			  
    		//_videoDisplay.attachCamera(null);

    		_ns.attachCamera(null);
			_ns.attachAudio(null)
    		
    		// Close NetStream
  			_ns.close();

   			 // Send FCUnpublish event to rmtp server
   		 	_nc.call("FCUnpublish",null);
  
   		

		}
		
		/**
 		* Handler for max duration reached
 		* */
		public var streamMaxDurationReached:Function
		public function streamMaxDurationReachedHandler():void
		{
			trace("stream max duration reached")
			stopRecording();
			//replayRecordedFlv();
		}
		
		
		private var tempClient:Object = new Object();
		private function onTempClientOnMetaDataHandler(e:Object):void
		{
			trace("on play data " + e)
			service.dispatchEvent(new SeesmicResultEvent(SeesmicResultEvent.RECORDING_RECORDED_VIDEO_META_DATA, e))
		}
		// Record stopped event
		private function streamStatusHandler(e:NetStatusEvent):void
		{
			trace("stream status handler " + e.info.code)
 		   if (e.info.code == "NetStream.Unpublish.Success") {

       			var tempNS:NetStream = new NetStream(this._nc)
       			tempClient. onMetaData = onTempClientOnMetaDataHandler
       			tempNS.client = tempClient
       			service.dispatchEvent(new SeesmicResultEvent(SeesmicResultEvent.RECORDING_STOP_RECORD,
       			{netstream:tempNS, netconnection:this._nc}))

 		   }

		}
		
		public function saveCurrentVideo(title:String,
		 inreplyto:String = null, urlname:String = null, twitter:Boolean = false, isPrivate:Boolean = false,
		 toUserName:String = null, language:String  = null):void
		{
			if(urlname == null) urlname = "seesmic-as3-lib"
			seesmicService.addEventListener(SeesmicResultEvent.VIDEOS_POST_VIDEO, onVideoPosted)
			seesmicService.video.postVideo(currentToken, title, urlname, inreplyto, twitter, isPrivate, toUserName)
			
		}
		
		private function onVideoPosted(e:SeesmicResultEvent):void
		{
			
			seesmicService.removeEventListener(SeesmicResultEvent.VIDEOS_POST_VIDEO, onVideoPosted)
			if(e.success)
			{
				var video_id:String = e.data.video_id
				seesmicService.addEventListener(SeesmicResultEvent.VIDEOS_GET_INFO, onVideoInfo)
				seesmicService.video.getInfo(video_id);
			}
			else
			{
				seesmicService.dispatchEvent(new SeesmicResultEvent(SeesmicResultEvent.RECORDING_SAVE_CURRENT_VIDEO,
				null, false, e.reason))
			}
			
		}
		
		private function onVideoInfo(e:SeesmicResultEvent):void
		{
			seesmicService.removeEventListener(SeesmicResultEvent.VIDEOS_GET_INFO, onVideoInfo)
			if(e.success)
			{
				
				seesmicService.dispatchEvent(new SeesmicResultEvent(SeesmicResultEvent.RECORDING_SAVE_CURRENT_VIDEO,
				e.data, true))
			}
			else
			{
				seesmicService.dispatchEvent(new SeesmicResultEvent(SeesmicResultEvent.RECORDING_SAVE_CURRENT_VIDEO,
				e.data, false, e.reason))
			}
		}

	}
}